<?php
/**
 * Created by PhpStorm.
 * User: shooke
 * Date: 17-2-15
 * Time: 上午10:31
 */

namespace corephp\exception;

use corephp\log\LogAbstract;

class Exception
{
    public $debug = false;
    /**
     * @var LogAbstract
     */
    public $logger;
    /**
     * 错误级别
     * @var array
     */
    protected $errorLevel = [
        E_ERROR             => 'E_ERROR',// (integer)	致命的运行时错误。这类错误一般是不可恢复的情况，例如内存分配导致的问题。后果是导致脚本终止不再继续运行。
        E_WARNING           => 'E_WARNING',// (integer)	运行时警告 (非致命错误)。仅给出提示信息，但是脚本不会终止运行。
        E_PARSE             => 'E_PARSE',// (integer)	编译时语法解析错误。解析错误仅仅由分析器产生。
        E_NOTICE            => 'E_NOTICE',// (integer)	运行时通知。表示脚本遇到可能会表现为错误的情况，但是在可以正常运行的脚本里面也可能会有类似的通知。
        E_CORE_ERROR        => 'E_CORE_ERROR',// (integer)	在PHP初始化启动过程中发生的致命错误。该错误类似 E_ERROR，但是是由PHP引擎核心产生的。	since PHP 4
        E_CORE_WARNING      => 'E_CORE_WARNING',// (integer)	PHP初始化启动过程中发生的警告 (非致命错误) 。类似 E_WARNING，但是是由PHP引擎核心产生的。	since PHP 4
        E_COMPILE_ERROR     => 'E_COMPILE_ERROR',// (integer)	致命编译时错误。类似E_ERROR, 但是是由Zend脚本引擎产生的。	since PHP 4
        E_COMPILE_WARNING   => 'E_COMPILE_WARNING',// (integer)	编译时警告 (非致命错误)。类似 E_WARNING，但是是由Zend脚本引擎产生的。	since PHP 4
        E_USER_ERROR        => 'E_USER_ERROR',// (integer)	用户产生的错误信息。类似 E_ERROR, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的。	since PHP 4
        E_USER_WARNING      => 'E_USER_WARNING',// (integer)	用户产生的警告信息。类似 E_WARNING, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的。	since PHP 4
        E_USER_NOTICE       => 'E_USER_NOTICE',// (integer)	用户产生的通知信息。类似 E_NOTICE, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的。	since PHP 4
        E_STRICT            => 'E_STRICT',// (integer)	启用 PHP 对代码的修改建议，以确保代码具有最佳的互操作性和向前兼容性。	since PHP 5
        E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',// (integer)	可被捕捉的致命错误。 它表示发生了一个可能非常危险的错误，但是还没有导致PHP引擎处于不稳定的状态。 如果该错误没有被用户自定义句柄捕获 (参见 set_error_handler())，将成为一个 E_ERROR　从而脚本会终止运行。	since PHP 5.2.0
        E_DEPRECATED        => 'E_DEPRECATED',// (integer)	运行时通知。启用后将会对在未来版本中可能无法正常工作的代码给出警告。	since PHP 5.3.0
        E_USER_DEPRECATED   => 'E_USER_DEPRECATED',// (integer)	用户产少的警告信息。 类似 E_DEPRECATED, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的。	since PHP 5.3.0
        E_ALL               => 'E_ALL',// (integer)	E_STRICT出外的所有错误和警告信息。30719 in PHP 5.3.x, 6143 in PHP 5.2.x, 2047 previously
    ];
    /**
     * 初始化处理
     */
    public function register()
    {
        ini_set('display_errors', $this->debug);
        set_exception_handler([$this, 'handleException']);
        set_error_handler([$this, 'handleError']);
        register_shutdown_function([$this, 'handleFatalError']);
    }

    /**
     * 恢复默认处理
     */
    public function unregister()
    {
        restore_error_handler();
        restore_exception_handler();
    }

    /**
     * 异常处理
     * @param \Exception $exception
     */
    public function handleException($exception)
    {
        //恢复默认处理
        $this->unregister();

        // 通知服务器，500代码错误
        http_response_code($exception->getCode());

        $exceptionMsg = $exception->getMessage().PHP_EOL.$exception->getTraceAsString();
        if($this->debug){
            echo $exceptionMsg;
        }
        $this->logger->error('exception-log',$exceptionMsg);

    }

    /**
     * 错误处理返回异常
     * @param $code
     * @param $message
     * @param $file
     * @param $line
     * @throws \ErrorException
     */
    public function handleError($code, $message, $file, $line)
    {
        throw new \ErrorException($message, $code, $code, $file, $line);
    }

    /**
     * 发生错误返回异常
     * @throws \ErrorException
     */
    public function handleFatalError()
    {
        $error = error_get_last();
        if(is_null($error)) return;

//        $errorMsg = $this->errorLevel[$error['type']]."  {$error['message']} ({$error['file']}:{$error['line']})\r\n";
//        $errorMsg .= debug_print_backtrace();
        if($this->debug){
            echo $error['message'];
        }
        $this->logger->error('error-log',$error['message']);

    }
}